package com.jse;

import java.util.Collection;
import java.util.List;
import java.util.function.IntPredicate;
import java.util.regex.Pattern;

/**
 * 提供了一系列静态方法来处理字符串。
 */
public class Strings {

    // 定义一个正则表达式模式，用于匹配中文字符
    public static final Pattern CHINESE = Pattern.compile("[\\u4e00-\\u9fa5]");
    private static final Pattern P_USCC = Pattern.compile("^(11|12|13|19|21|29|31|32|33|34|35|39|41|49|51|52|53|59|61|62"
            + "|69|71|72|79|81|82|91|92|93|A1|A2|N1|N2|N3|N9|Y1)[1-9]{1}[0-9]{5}[0-9A-Z]{9}[0-9A-Z]{1}$");
    private static final IntPredicate isDigitPredicate = Character::isDigit;

    // 空值检查相关的方法
    /**
     * 判断字符串是否为空或长度为零。
     *
     * @param s 要检查的字符串
     * @return 如果字符串为空或长度为零，则返回 true；否则返回 false
     */
    public static boolean isEmpty(CharSequence s) { return s == null || s.length() == 0; }

    /**
     * 判断字符串是否非空。
     *
     * @param s 要检查的字符串
     * @return 如果字符串非空，则返回 true；否则返回 false
     */
    public static boolean isNotEmpty(CharSequence s) { return !isEmpty(s); }

    /**
     * 判断字符串是否只包含空白字符或者为空。
     *
     * @param s 要检查的字符串
     * @return 如果字符串只包含空白字符或者为空，则返回 true；否则返回 false
     */
    public static boolean isBlank(String s) { return s == null || s.isBlank(); }

    /**
     * 判断字符串是否非空且不只包含空白字符。
     *
     * @param s 要检查的字符串
     * @return 如果字符串非空且不只包含空白字符，则返回 true；否则返回 false
     */
    public static boolean hasText(CharSequence s) {
        if (s == null) {
            return false;
        }
        int strLen = s.length();
        if (strLen == 0) {
            return false;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(s.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    // 字符串存在性检查
    /**
     * 检查字符串中是否包含中文字符。
     *
     * @param str 要检查的字符串
     * @return 如果字符串中包含中文字符，则返回 true；否则返回 false
     */
    public static boolean hasChinese(CharSequence str) { return CHINESE.matcher(str).find(); }

    /**
     * 检查字符串中是否包含大写字母。
     *
     * @param s 要检查的字符串
     * @return 如果字符串中包含大写字母，则返回 true；否则返回 false
     */
    public static boolean hasUpperCase(CharSequence s) { return s.chars().anyMatch(c -> Character.isUpperCase(c)); }

    // 字符串转换
    /**
     * 将字符串的首字母转换为小写。
     *
     * @param s 要转换的字符串
     * @return 首字母小写的字符串
     */
    public static String firstLowerCase(String s) { return Character.toLowerCase(s.charAt(0)) + s.substring(1); }

    /**
     * 将字符串的首字母转换为大写。
     *
     * @param s 要转换的字符串
     * @return 首字母大写的字符串
     */
    public static String firstUpperCase(String s) { return Character.toUpperCase(s.charAt(0)) + s.substring(1); }

    /**
     * 将字符串转换为驼峰式命名。
     * 
     * @param str 要转换的字符串
     * @param toLowerCaseAnyway 是否无条件将所有字符转换为小写
     * @return 驼峰式的字符串
     */
    public static String toCamelCase(String str, boolean toLowerCaseAnyway) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        StringBuilder sb = new StringBuilder();
        boolean nextUpperCase = false; // 标记下一个字符是否需要转换为大写
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (ch == '_') {// 如果当前字符是下划线，则标记下一个字符为大写
                nextUpperCase = true;
            } else {
                // 如果是首字母并且 toLowerCaseAnyway 为 true，转换为小写
                if (sb.length() == 0 && toLowerCaseAnyway) {
                    sb.append(Character.toLowerCase(ch));
                } else if (nextUpperCase) {
                    sb.append(Character.toUpperCase(ch));
                    nextUpperCase = false; // 清除标记
                } else {
                    sb.append(toLowerCaseAnyway ? Character.toLowerCase(ch) : ch);
                }
            }
        }
        return sb.toString();
    }

    // 字符串默认值处理
    /**
     * 如果第一个字符串为空，则返回第二个字符串；否则返回第一个字符串。
     *
     * @param c 第一个字符串
     * @param d 第二个字符串
     * @return 如果 c 为空，则返回 d；否则返回 c
     */
    public static String def(CharSequence c, CharSequence d) { return isEmpty(c) ? d.toString() : c.toString(); }

    /**
     * 连接 Iterable 中的元素为一个字符串。
     *
     * @param iterable 要连接的 Iterable 对象
     * @param separator 分隔符
     * @return 连接后的字符串
     */
    public static String join(Iterable<?> iterable, String separator) {
        if (iterable == null) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        boolean isFirst = true;
        for (Object item : iterable) {
            if (!isFirst) {
                sb.append(separator);
            }
            sb.append(item);
            isFirst = false;
        }
        return sb.toString();
    }

    // 字符串格式验证
    /**
     * 检查字符串是否包含通配符 '*' 或 '?'。
     *
     * @param s 要检查的字符串
     * @return 如果字符串包含通配符，则返回 true；否则返回 false
     */
    public static boolean isPattern(String s) { return (s.indexOf('*') != -1 || s.indexOf('?') != -1); }

    /**
     * 检查字符串是否符合中国社会信用代码格式。
     *
     * @param cs 要检查的字符串
     * @return 如果字符串符合中国社会信用代码格式，则返回 true；否则返回 false
     */
    public static boolean isUSCC(CharSequence cs) {
        return P_USCC.matcher(cs).find();
    }

    /**
     * 检查字符串是否仅由数字组成。
     *
     * @param s 要检查的字符串
     * @return 如果字符串仅由数字组成，则返回 true；否则返回 false
     */
    public static boolean isNumber(CharSequence s) { return isNotEmpty(s) && s.chars().allMatch(isDigitPredicate); }
    // 字符串比较
    /**
     * 比较两个字符串是否相等。
     *
     * @param a 第一个字符串
     * @param b 第二个字符串
     * @return 如果两个字符串相等，则返回 true；否则返回 false
     */
    public static boolean equals(String a, String b) {
        return a == null ? b == null : a.equals(b);
    }

    /**
     * 主函数示例。
     */
    public static void main(String[] args) {
        System.out.println(join(List.of("a", "b", "c"), ","));
    }
}